package snafu.implementation.agents;

import java.awt.Color;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.List;

import snafu.framework.actions.AbstractAction;
import snafu.framework.actions.AbstractReaction;
import snafu.framework.agents.Agent;
import snafu.framework.agents.AgentBrain;
import snafu.framework.agents.AgentState;
import snafu.framework.agents.AgentStateItself;
import snafu.framework.objects.WorldObject;
import snafu.framework.senses.SenseItself;
import snafu.framework.view.Access;
import snafu.framework.worlds.Position;
import snafu.framework.worlds.WorldMap;
import snafu.implementation.actions.kill.KillIntention;
import snafu.implementation.actions.kill.KillIntentionItself;
import snafu.implementation.actions.turn.left.TurnLeftIntention;
import snafu.implementation.actions.turn.left.TurnLeftIntentionItself;
import snafu.implementation.actions.turn.right.TurnRightIntention;
import snafu.implementation.actions.turn.right.TurnRightIntentionItself;
import snafu.implementation.actions.walk.forward.WalkForwardIntention;
import snafu.implementation.actions.walk.forward.WalkForwardIntentionItself;
import snafu.implementation.objects.stench.StenchItself;
import snafu.implementation.senses.stimuli.light.LightStimulus;
import snafu.implementation.senses.stimuli.ultrasound.UltrasoundStimulus;
import snafu.implementation.senses.stimuli.ultrasound.UltrasoundStimulusItself;
import snafu.implementation.states.literals.color.ColorLiteralItself;
import snafu.implementation.states.literals.depth.DepthLiteralItself;
import snafu.implementation.states.literals.direction.DirectionLiteralItself;
import snafu.implementation.states.literals.position.PositionLiteral;
import snafu.implementation.states.literals.shape.ShapeLiteralItself;
import snafu.implementation.states.literals.surround.SurroundLiteralItself;

public class RandomWumpus extends AgentBrain {
	@Override
	public AgentStateItself getInitialState() {
		// create shape
		int[] xPoints = new int[] {0, -43, 43};
		int[] yPoints = new int[] {-50, 25, 25};
		Polygon p = new Polygon(xPoints, yPoints, 3);
		Rectangle r = new Rectangle(-50, -50, 100, 30);
		Area shape = new Area(p);
		shape.subtract(new Area(r));
		
		// create state
		AgentStateItself state = new AgentStateItself();
		
		// literals
		state.setLiteral(new DirectionLiteralItself(0, Access.PUBLIC));
		state.addLiteral(new ColorLiteralItself(Color.DARK_GRAY, Access.PUBLIC));
		state.addLiteral(new DepthLiteralItself(10, Access.PUBLIC));
		state.addLiteral(new SurroundLiteralItself(new StenchItself(), 1, Access.PUBLIC));
		state.setLiteral(new ShapeLiteralItself(shape, Access.PUBLIC));

		// intentions
		state.addIntention(new KillIntentionItself(Access.PRIVATE));
		state.addIntention(new WalkForwardIntentionItself(Access.PRIVATE));
		state.addIntention(new TurnLeftIntentionItself(Access.PRIVATE));
		state.addIntention(new TurnRightIntentionItself(Access.PRIVATE));

		// senses
		state.addSense(new SenseItself(LightStimulus.class, 0, 100));
		state.addSense(new SenseItself(UltrasoundStimulus.class, 0, 100));
		
		// stimuli
		state.addStimulus(new UltrasoundStimulusItself(0, 100));
		
		return state;
	}

	@Override
	public AbstractAction act(WorldMap perception, AgentState state) {

		Position position = state.getLiteral(PositionLiteral.class);
		List<AbstractAction> possibleActions = new ArrayList<AbstractAction>();

		// kill any agent that is on the same field
		KillIntention kill = state.getIntention(KillIntention.class);
		if (kill != null) {
			for (WorldObject object : perception.get(position).getWorldObjects()) {
				// the object is an agent
				if (Agent.class.isAssignableFrom(object.getClass())) {
					Agent agent = (Agent) object;
					// the agent is a gold seeking hiker
					if (GoldSeekingHiker.class.isAssignableFrom(agent.getBrain())) {
						// kill him!
						if (kill.isApplicable(perception, state, object)) {
							return kill.createAction(object);
						}
					}
				}
			}
		}
		
		WalkForwardIntention walk = state.getIntention(WalkForwardIntention.class);
		if (walk != null && walk.isApplicable(perception, state)) {
			possibleActions.add(walk.createAction());
			possibleActions.add(walk.createAction());
		}
		
		TurnLeftIntention left = state.getIntention(TurnLeftIntention.class);
		if (left != null && left.isApplicable(perception, state)) {
			possibleActions.add(left.createAction());
		}
		
		TurnRightIntention right = state.getIntention(TurnRightIntention.class);
		if (right != null && right.isApplicable(perception, state)) {
			possibleActions.add(right.createAction());
		}

		int index = (int) (Math.random() * possibleActions.size());
		return possibleActions.get(index);
	}

	@Override
	public AbstractReaction react(AbstractAction action) {
		return null;
	}

	@Override
	public String output() {
		return "RandomWumpus";
	}
}
